package com.cmc.cloud.cmclink.doc.service.impl.so;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cmc.cloud.cmclink.doc.api.document.emums.RequireTypeCodeEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.SoSiEnum;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.RequirementsErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.convert.RequirementsConvert;
import com.cmc.cloud.cmclink.doc.entity.RequirementsDO;
import com.cmc.cloud.cmclink.doc.mapper.RequirementsMapper;
import com.cmc.cloud.cmclink.doc.service.so.RequirementsService;
import com.cmc.cloud.cmclink.doc.vo.sovo.requirementsvo.RequirementsCreateReqVO;
import com.cmc.cloud.cmclink.doc.vo.sovo.requirementsvo.RequirementsPageReqVO;
import com.cmc.cloud.cmclink.doc.vo.sovo.requirementsvo.RequirementsRespVO;
import com.cmc.cloud.cmclink.doc.vo.sovo.requirementsvo.RequirementsUpdateReqVO;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;
import com.cmes.framework.common.pojo.PageResult;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * 订舱附加要求 Service 实现类
 *
 * @author 招商轮船-管理员
 */
@Service
@Validated
public class RequirementsServiceImpl implements RequirementsService {

    @Resource
    private RequirementsMapper requirementsMapper;

    @Override
    public void createRequirements(RequirementsCreateReqVO createReqVO) {
        // 插入
        RequirementsDO requirements = RequirementsConvert.INSTANCE.convert(createReqVO);
        requirementsMapper.insert(requirements);
    }

    @Override
    public void createBatch(List<RequirementsCreateReqVO> createReqVOList) {
        // 插入
        List<RequirementsDO> list = RequirementsConvert.INSTANCE.convertBatch(createReqVOList);
        requirementsMapper.insertBatch(list);
    }

    @Override
    public void createOrUpdateAndDeleteBatch(Long referenceId, String referenceType, List<RequirementsUpdateReqVO> newList, List<RequirementsRespVO> oldList) {
        // 无效数据直接返回
        if (CollectionUtil.isEmpty(newList) && CollectionUtil.isEmpty(oldList)) {
            return;
        }
        // 默认值
        if (CollectionUtil.isEmpty(newList)) {
            newList = new ArrayList<>();
        }
        if (CollectionUtil.isEmpty(oldList)) {
            oldList = new ArrayList<>();
        }
        List<RequirementsUpdateReqVO> createList = new ArrayList<>();
        List<RequirementsUpdateReqVO> updateList = new ArrayList<>();
        // 历史数据
        Set<Long> oldIds = oldList.stream().map(RequirementsRespVO::getId).collect(Collectors.toSet());
        //默认为特殊单证要求类型
        newList.forEach(n-> n.setRequireTypeCode("Doc Request"));
        newList.forEach(e -> {
            if (e.getId() != null) {
                if (oldIds.contains(e.getId())) {
                    // 正常更新
                    updateList.add(e);
                    oldIds.remove(e.getId()); // 剩下的数据需要删除
                } else {
                    // 数据更新非法
                    throw ServiceExceptionUtil.exception(RequirementsErrorCodeConstants.REQUIREMENTS_NOT_EXISTS);
                }
            } else {
                e.setReferenceId(referenceId);
                e.setReferenceType(referenceType);
                createList.add(e);
            }
        });
        if (CollectionUtil.isNotEmpty(oldIds)) {
            // 没有匹配上的就是前端删除的
            requirementsMapper.deleteBatchIds(oldIds);
        }
        if (CollectionUtil.isNotEmpty(createList)) {
            List<RequirementsDO> requirementsCreateList = RequirementsConvert.INSTANCE.convertBatchUpdate(createList);
            requirementsMapper.insertBatch(requirementsCreateList);
        }
        if (CollectionUtil.isNotEmpty(updateList)) {
            List<RequirementsDO> requirementsUpdateList = RequirementsConvert.INSTANCE.convertBatchUpdate(updateList);
            requirementsMapper.updateBatch(requirementsUpdateList);
        }
    }

    @Override
    public void updateRequirements(RequirementsUpdateReqVO updateReqVO) {
        // 校验存在
        validateRequirementsExists(updateReqVO.getId());
        // 更新
        RequirementsDO updateObj = RequirementsConvert.INSTANCE.convert(updateReqVO);
        requirementsMapper.updateById(updateObj);
    }

    @Override
    public void deleteRequirements(Long id) {
        // 校验存在
        validateRequirementsExists(id);
        // 删除
        requirementsMapper.deleteById(id);
    }

    private void validateRequirementsExists(Long id) {
        if (requirementsMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(RequirementsErrorCodeConstants.REQUIREMENTS_NOT_EXISTS);
        }
    }

    @Override
    public RequirementsDO getRequirements(Long id) {
        return requirementsMapper.selectById(id);
    }

    @Override
    public List<RequirementsDO> getRequirementByBlnoId(Long id) {
        LambdaQueryWrapper<RequirementsDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RequirementsDO::getReferenceId, id);
        queryWrapper.orderByAsc(RequirementsDO::getId);
        return requirementsMapper.selectList(queryWrapper);
    }

    @Override
    public List<RequirementsDO> getRequirementsList(Collection<Long> ids) {
        return requirementsMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<RequirementsDO> getRequirementsPage(RequirementsPageReqVO reqVO) {
        LambdaQueryWrapperX<RequirementsDO> queryWrapper = new LambdaQueryWrapperX<>();
        return requirementsMapper.selectPage(reqVO, queryWrapper);
    }

    @Override
    public void deleteByReferenceIds(Collection<Long> referenceIds, String referenceType) {
        LambdaUpdateWrapper<RequirementsDO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(RequirementsDO::getReferenceId, referenceIds);
        updateWrapper.eq(RequirementsDO::getReferenceType, referenceType);
        requirementsMapper.delete(updateWrapper);
    }

    @Override
    public List<RequirementsDO> seleteByReferenceId(Long referenceId, String referenceType) {
        LambdaQueryWrapper<RequirementsDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(RequirementsDO::getReferenceId, referenceId);
        queryWrapper.eq(RequirementsDO::getReferenceType, referenceType);
        queryWrapper.orderByAsc(RequirementsDO::getId);
        return requirementsMapper.selectList(queryWrapper);
    }

    @Override
    public List<RequirementsDO> getRequirementsSelected(Long soId) {
        LambdaQueryWrapper<RequirementsDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(RequirementsDO::getReferenceId, soId);
        queryWrapper.eq(RequirementsDO::getReferenceType, SoSiEnum.SO.getValue());
        queryWrapper.eq(RequirementsDO::getRequireTypeCode, RequireTypeCodeEnum.LOADINGREQUEST.getValue());
        queryWrapper.orderByAsc(RequirementsDO::getId);
        return requirementsMapper.selectList(queryWrapper);
    }
}
